SPB Git
2.0 KB · 27 lines tsx
1import type { Metadata } from "next";2import Link from "next/link";3import { notFound } from "next/navigation";4import { getCollection, listCollections } from "@/lib/public/queries";5import { Breadcrumbs } from "@/components/breadcrumbs";6import { ToolCard } from "@/components/tool-card";7import { fmtDate } from "@/lib/utils";8export const revalidate = 600;9export async function generateStaticParams() { try { return (await listCollections()).map((c) => ({ slug: c.slug })); } catch { return []; } }10export async function generateMetadata({ params }: { params: Promise<{ slug: string }> }): Promise<Metadata> {11  const c = await getCollection((await params).slug); if (!c) return { title: "Not found" };12  return { title: c.title, description: c.description.slice(0, 160), alternates: { canonical: `/collections/${c.slug}` } };13}14export default async function CollectionPage({ params }: { params: Promise<{ slug: string }> }) {15  const c = await getCollection((await params).slug); if (!c) notFound();16  return (17    <div className="mx-auto max-w-7xl px-4 py-8 sm:px-6">18      <Breadcrumbs items={[{ href: "/collections", label: "Collections" }, { label: c.title }]} />19      <h1 className="display h1 mt-3">{c.title}</h1>20      <p className="prose-tool mt-3 max-w-3xl">{c.description}</p>21      <p className="mt-2 text-xs text-fg-3">{c.items.length} tools · updated {fmtDate(c.updatedAt)} · <Link href={`/compare?tools=${c.items.slice(0, 4).map((i) => i.slug).join(",")}`} rel="nofollow" className="text-accent hover:underline">compare the first four</Link></p>22      <h2 className="sr-only">Tools in this collection</h2>23      <ol className="mt-8 grid gap-4 sm:grid-cols-2 lg:grid-cols-3">{c.items.map((t, i) => <li key={t.id} className="relative"><span className="absolute -left-1 -top-2 z-10 grid h-6 w-6 place-items-center rounded-full bg-accent text-xs font-semibold text-accent-fg" aria-hidden>{i + 1}</span><ToolCard t={t} blurb={t.blurb} className="h-full" /></li>)}</ol>24    </div>25  );26}27
Files · main
Menu

Theme